Skip to main content

libobs_wrapper\scenes\scene_item/
traits.rs

1use crate::scenes::{ObsSceneItemRef, ObsSceneRef, SceneItemTrait};
2use crate::sources::{ObsSourceRef, ObsSourceTrait};
3use crate::utils::{ObsError, SourceInfo};
4use std::sync::Arc;
5
6pub trait SceneItemExtSceneTrait {
7    /// Adds the specified source to this scene. Returns a reference to the created scene item.
8    /// You can use that SceneItemPtr to manipulate the source within this scene (position, scale, rotation, etc).
9    fn add_source<T: ObsSourceTrait + Clone + 'static>(
10        &mut self,
11        source: T,
12    ) -> Result<ObsSceneItemRef<T>, ObsError>;
13
14    /// Creates and adds a source to this scene based on the given `SourceInfo`.
15    /// Returns a reference to the created scene item, which internally holds the created source.
16    fn add_and_create_source(
17        &mut self,
18        info: SourceInfo,
19    ) -> Result<ObsSceneItemRef<ObsSourceRef>, ObsError>;
20
21    /// Gets a source by name from this scene. Returns None if no source with the given name exists in this scene.
22    fn get_source(&self, name: &str) -> Result<Option<Arc<dyn ObsSourceTrait>>, ObsError>;
23
24    #[deprecated = "Use get_source; the returned shared handle was never a mutable reference"]
25    fn get_source_mut(&self, name: &str) -> Result<Option<Arc<dyn ObsSourceTrait>>, ObsError> {
26        self.get_source(name)
27    }
28
29    /// Removes the given source from this scene. Removes the corresponding scene item as well. It may be possible that this source is still added to another scene.
30    fn remove_every_item_of_source<T: ObsSourceTrait>(&mut self, source: T)
31        -> Result<(), ObsError>;
32
33    /// Removes a specific scene item from this scene immediately.
34    fn remove_item<K: SceneItemTrait + ?Sized>(&mut self, scene_item: &K) -> Result<(), ObsError>;
35
36    #[deprecated = "Use remove_item; it removes the native scene item immediately without consuming the handle"]
37    fn remove_scene_item<K: SceneItemTrait>(&mut self, scene_item: K) -> Result<(), ObsError> {
38        self.remove_item(&scene_item)
39    }
40
41    /// Removes all sources from this scene.
42    fn remove_all_sources(&mut self) -> Result<(), ObsError>;
43
44    /// Gets the underlying scene item pointers for the given source in this scene.
45    ///
46    /// A scene item is basically the representation of a source within this scene. It holds information about the position, scale, rotation, etc.
47    fn items_for_source<T: ObsSourceTrait + Clone>(
48        &self,
49        source: &T,
50    ) -> Result<Vec<Arc<dyn SceneItemTrait>>, ObsError>;
51
52    #[deprecated = "Use items_for_source; scene item handles are managed objects, not raw pointers"]
53    fn get_scene_item_ptr<T: ObsSourceTrait + Clone>(
54        &self,
55        source: &T,
56    ) -> Result<Vec<Arc<dyn SceneItemTrait>>, ObsError> {
57        self.items_for_source(source)
58    }
59}
60
61impl SceneItemExtSceneTrait for ObsSceneRef {
62    fn add_source<T: ObsSourceTrait + Clone + 'static>(
63        &mut self,
64        source: T,
65    ) -> Result<ObsSceneItemRef<T>, ObsError> {
66        self.runtime.ensure_same_runtime(source.runtime())?;
67        let scene_item = ObsSceneItemRef::new(self, source.clone(), self.runtime.clone())?;
68
69        let scene_clone = scene_item.clone();
70        self.attached_scene_items
71            .write()
72            .map_err(|e| ObsError::LockError(format!("{:?}", e)))?
73            .entry(source.__native_handle().native_id())
74            .or_insert_with(|| (Arc::new(source), Vec::new()))
75            .1
76            .push(Arc::new(scene_clone));
77
78        Ok(scene_item)
79    }
80
81    fn add_and_create_source(
82        &mut self,
83        info: SourceInfo,
84    ) -> Result<ObsSceneItemRef<ObsSourceRef>, ObsError> {
85        let source = crate::sources::ObsSourceRef::new(
86            info.id,
87            info.name,
88            info.settings,
89            info.hotkey_data,
90            self.runtime.clone(),
91        )?;
92
93        let scene_item = self.add_source(source.clone())?;
94        Ok(scene_item)
95    }
96
97    fn get_source(&self, name: &str) -> Result<Option<Arc<dyn ObsSourceTrait>>, ObsError> {
98        let guard = self
99            .attached_scene_items
100            .read()
101            .map_err(|e| ObsError::LockError(format!("{:?}", e)))?;
102        Ok(guard
103            .values()
104            .find(|(source, _)| source.name() == name)
105            .map(|(source, _)| source.clone()))
106    }
107
108    fn remove_every_item_of_source<T: ObsSourceTrait>(
109        &mut self,
110        source: T,
111    ) -> Result<(), ObsError> {
112        self.runtime.ensure_same_runtime(source.runtime())?;
113        let source_id = source.__native_handle().native_id();
114
115        let mut guard = self
116            .attached_scene_items
117            .write()
118            .map_err(|e| ObsError::LockError(format!("{:?}", e)))?;
119        let items = guard
120            .get(&source_id)
121            .map(|(_, items)| items.clone())
122            .unwrap_or_default();
123        for item in items {
124            item.remove_from_scene()?;
125        }
126        guard.remove(&source_id);
127
128        Ok(())
129    }
130
131    fn remove_item<K: SceneItemTrait + ?Sized>(&mut self, scene_item: &K) -> Result<(), ObsError> {
132        self.runtime.ensure_same_runtime(&scene_item.runtime())?;
133        // Group removal needs to inspect/prune this same registry in order to invalidate child
134        // handles. Do not hold the registry lock while dispatching polymorphic removal behavior.
135        scene_item.remove_from_scene()?;
136        let mut guard = self
137            .attached_scene_items
138            .write()
139            .map_err(|e| ObsError::LockError(format!("{:?}", e)))?;
140
141        guard.retain(|_, (_, items)| {
142            items.retain(|item| {
143                // Keep everything except this one scene item
144                item.object_id() != scene_item.object_id()
145            });
146            // Remove the entry if no items remain
147            !items.is_empty()
148        });
149        drop(guard);
150        self.attached_groups
151            .write()
152            .map_err(|e| ObsError::LockError(format!("{e:?}")))?
153            .retain(|group| group.object_id() != scene_item.object_id());
154        Ok(())
155    }
156
157    fn remove_all_sources(&mut self) -> Result<(), ObsError> {
158        let mut guard = self
159            .attached_scene_items
160            .write()
161            .map_err(|e| ObsError::LockError(format!("{:?}", e)))?;
162        let items = guard
163            .values()
164            .flat_map(|(_, items)| items.iter().cloned())
165            .collect::<Vec<_>>();
166        for item in items {
167            item.remove_from_scene()?;
168        }
169        guard.clear();
170
171        Ok(())
172    }
173
174    fn items_for_source<T: ObsSourceTrait + Clone>(
175        &self,
176        source: &T,
177    ) -> Result<Vec<Arc<dyn SceneItemTrait>>, ObsError> {
178        self.runtime.ensure_same_runtime(source.runtime())?;
179        let guard = self
180            .attached_scene_items
181            .read()
182            .map_err(|e| ObsError::LockError(format!("{:?}", e)))?;
183
184        let res = guard
185            .get(&source.__native_handle().native_id())
186            .map(|(_, scene_items)| scene_items.clone())
187            .unwrap_or_default();
188
189        Ok(res)
190    }
191}